#include "pwm.h"

void PWM_QuickInit(TIM_TypeDef * TIMx, PWM_Channel Channelx, uint32_t Frequence, FunctionalState ENABLE_OR_DISABL)
{
    uint16_t Prescaler = 1;
    
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    if(TIMx == TIM4)
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
        switch(Channelx)
        {
        case Channel1: GPIO_QuickInit(GPIOB, GPIO_Pin_6, GPIO_Mode_AF_PP); break;
        case Channel2: GPIO_QuickInit(GPIOB, GPIO_Pin_7, GPIO_Mode_AF_PP); break;
        case Channel3: GPIO_QuickInit(GPIOB, GPIO_Pin_8, GPIO_Mode_AF_PP); break;
        case Channel4: GPIO_QuickInit(GPIOB, GPIO_Pin_9, GPIO_Mode_AF_PP); break;
        }
    }
    if(TIMx == TIM3)
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);       
        switch(Channelx)
        {
        case Channel1: GPIO_QuickInit(GPIOA, GPIO_Pin_6, GPIO_Mode_AF_PP); break;
        case Channel2: GPIO_QuickInit(GPIOA, GPIO_Pin_7, GPIO_Mode_AF_PP); break;
        case Channel3: GPIO_QuickInit(GPIOB, GPIO_Pin_0, GPIO_Mode_AF_PP); break;
        case Channel4: GPIO_QuickInit(GPIOB, GPIO_Pin_1, GPIO_Mode_AF_PP); break;
        }
    }
    if(TIMx == TIM2)
    {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        switch(Channelx)
        {
        case Channel1: GPIO_QuickInit(GPIOA, GPIO_Pin_0, GPIO_Mode_AF_PP); break;
        case Channel2: GPIO_QuickInit(GPIOA, GPIO_Pin_1, GPIO_Mode_AF_PP); break;
        case Channel3: GPIO_QuickInit(GPIOA, GPIO_Pin_2, GPIO_Mode_AF_PP); break;
        case Channel4: GPIO_QuickInit(GPIOA, GPIO_Pin_3, GPIO_Mode_AF_PP); break;
        }
    }
    if(TIMx == TIM1)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
        switch(Channelx)
        {
        case Channel1: GPIO_QuickInit(GPIOA, GPIO_Pin_8, GPIO_Mode_AF_PP); break;
        case Channel2: GPIO_QuickInit(GPIOA, GPIO_Pin_9, GPIO_Mode_AF_PP); break;
        case Channel3: GPIO_QuickInit(GPIOA, GPIO_Pin_10, GPIO_Mode_AF_PP); break;
        case Channel4: GPIO_QuickInit(GPIOA, GPIO_Pin_11, GPIO_Mode_AF_PP); break;
        }
    }
    
    while(Frequence < 2000)
    {
        Frequence *= 2;
        Prescaler *= 2;
    }
    
    TIM_TimeBaseStructure.TIM_Period = (72000000 / Frequence - 1); 
    TIM_TimeBaseStructure.TIM_Prescaler = Prescaler - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    
    if(Channelx == Channel1)
    {
        TIM_OC1Init(TIMx, &TIM_OCInitStructure);  
        TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);
    }
    if(Channelx == Channel2)
    {
        TIM_OC2Init(TIMx, &TIM_OCInitStructure);  
        TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable);
    }
    if(Channelx == Channel3)
    {
        TIM_OC3Init(TIMx, &TIM_OCInitStructure);  
        TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);
    }
    if(Channelx == Channel4)
    {
        TIM_OC4Init(TIMx, &TIM_OCInitStructure);  
        TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Enable);
    }
    
    TIM_Cmd(TIMx, ENABLE_OR_DISABL);
}

void PWM_Change(TIM_TypeDef * TIMx, PWM_Channel Channelx, uint16_t D) //D = 0.5 = 5000
{
    uint16_t arr = TIMx->ARR;
    switch(Channelx)
    {
        case Channel1: TIM_SetCompare1(TIMx, arr * (10000 - D) / 10000 + 1); break;
        case Channel2: TIM_SetCompare2(TIMx, arr * (10000 - D) / 10000 + 1); break;
        case Channel3: TIM_SetCompare3(TIMx, arr * (10000 - D) / 10000 + 1); break;
        case Channel4: TIM_SetCompare4(TIMx, arr * (10000 - D) / 10000 + 1); break;
    }
}
